Pallial transition state cells

Extract apical progenitors

We perform Kmeans clustering on the 4 cell state scores :

  • Sub-pallial neurons SP
  • Pallial neurons Pal
  • Sub-pallial BP SP.BP
  • Pallial BP Pal.BP

We then extract the Pallial cells branche. We also excludes CR cells cluster form the trajectory inference.

#Remove the sub-pallial cells branche
MeanKclust.SPscore <- aggregate(SP_signature1 ~ kmeanClust, Allcells.data@meta.data, mean)
SPclust <- MeanKclust.SPscore %>% filter(SP_signature1 == max(SP_signature1)) %>% pull(kmeanClust)

SP.cells <- Allcells.data@meta.data %>% filter(kmeanClust == SPclust) %>% pull(Barcodes)

# Remove cells not use for trajectory inference (Subpallial cells defined by kmeans, Late GABA neurons and CR cells)
Excluded.clusters <- Allcells.data@meta.data %>%
                  filter(Cluster.ident %in% grep("*Sub|GABA|LN.Glut.13|LN.Glut.14|LN.Glut.1$", unique(as.character(Allcells.data@ident)), value = T)) %>%
                  pull(Barcodes) 

# We further keep only pallial apical progenitor cluster among other AP clusters
MeanKclust.APscore <- aggregate(AP_signature1 ~ kmeanClust, Allcells.data@meta.data, mean)
APclust <- MeanKclust.APscore %>% filter(AP_signature1 == max(AP_signature1)) %>% pull(kmeanClust)

All.AP <- Allcells.data@meta.data %>% filter(kmeanClust == APclust) %>% pull(Barcodes)
Valide.AP <- Allcells.data@meta.data %>% filter(Cluster.ident %in% grep("Dorsal.Pallium|lateral.Pallium.1|lateral.Pallium.2|Ventral.Pallium",
                                                unique(as.character(Allcells.data@ident)), value = T)) %>% pull(Barcodes)

filtered.AP <- All.AP[!All.AP %in% Valide.AP]

#Remove all invalide cells + 3 pallial outlier cells
Cells.to.use <- rownames(Allcells.data@meta.data)[!rownames(Allcells.data@meta.data) %in% unique(c(SP.cells, Excluded.clusters, filtered.AP, c("ATTTCTGCACGGCCAT" , "CAAGTTGCAAGCCTAT", "CTACATTGTAGCTGCC")))]
Allcells.data <- SubsetData(Allcells.data, cells.use = Cells.to.use, subset.raw = T,  do.clean = F)

Compute cells’ fate bias along tpward each mature neuronal types

Prepare FateID input data

We restricted the analysis to the most variable genes as dertermined by the Seurat function “FindVariableGenes” excluding cell cylce phase genes

Compte the cells’ fate bias

## minnr: 10 
## minnrh: 30 
## test set size iteration 1 : 10 10 10 10 10 10 10 
## randomforest iteration 1 of 50 cells
## test set size iteration 2 : 10 10 10 10 10 10 10 
## randomforest iteration 2 of 62 cells
## test set size iteration 3 : 10 10 10 10 10 10 10 
## randomforest iteration 3 of 53 cells
## test set size iteration 4 : 10 10 10 10 10 10 10 
## randomforest iteration 4 of 55 cells
## test set size iteration 5 : 10 10 10 10 10 10 10 
## randomforest iteration 5 of 49 cells
## test set size iteration 6 : 10 10 10 10 10 10 10 
## randomforest iteration 6 of 48 cells
## test set size iteration 7 : 10 10 10 10 10 10 10 
## randomforest iteration 7 of 54 cells
## test set size iteration 8 : 10 10 10 10 10 10 10 
## randomforest iteration 8 of 49 cells
## test set size iteration 9 : 10 10 10 10 10 10 10 
## randomforest iteration 9 of 50 cells
## test set size iteration 10 : 10 10 10 10 10 10 10 
## randomforest iteration 10 of 51 cells
## test set size iteration 11 : 10 10 10 10 10 10 10 
## randomforest iteration 11 of 52 cells
## test set size iteration 12 : 10 10 10 10 10 10 10 
## randomforest iteration 12 of 44 cells
## test set size iteration 13 : 10 10 10 10 10 10 10 
## randomforest iteration 13 of 45 cells
## test set size iteration 14 : 10 10 10 10 10 10 10 
## randomforest iteration 14 of 42 cells
## test set size iteration 15 : 10 10 10 10 10 10 10 
## randomforest iteration 15 of 43 cells
## test set size iteration 16 : 10 10 10 10 10 10 10 
## randomforest iteration 16 of 40 cells
## test set size iteration 17 : 10 10 10 10 10 10 10 
## randomforest iteration 17 of 40 cells
## test set size iteration 18 : 10 10 10 10 10 10 10 
## randomforest iteration 18 of 37 cells
## test set size iteration 19 : 10 10 10 10 10 10 10 
## randomforest iteration 19 of 42 cells
## test set size iteration 20 : 10 10 10 10 10 10 10 
## randomforest iteration 20 of 43 cells
## test set size iteration 21 : 10 10 10 10 10 10 10 
## randomforest iteration 21 of 48 cells
## test set size iteration 22 : 10 10 10 10 10 10 10 
## randomforest iteration 22 of 47 cells
## test set size iteration 23 : 10 10 10 10 10 10 10 
## randomforest iteration 23 of 50 cells
## test set size iteration 24 : 10 10 10 10 10 10 10 
## randomforest iteration 24 of 52 cells
## test set size iteration 25 : 10 10 10 10 10 10 10 
## randomforest iteration 25 of 53 cells
## test set size iteration 26 : 10 10 10 10 10 10 10 
## randomforest iteration 26 of 57 cells
## test set size iteration 27 : 10 10 10 10 10 10 10 
## randomforest iteration 27 of 54 cells
## test set size iteration 28 : 10 10 10 10 10 10 10 
## randomforest iteration 28 of 49 cells
## test set size iteration 29 : 10 10 10 10 10 10 10 
## randomforest iteration 29 of 54 cells
## test set size iteration 30 : 10 10 10 10 10 10 10 
## randomforest iteration 30 of 51 cells
## test set size iteration 31 : 10 10 10 10 10 10 10 
## randomforest iteration 31 of 50 cells
## test set size iteration 32 : 10 10 10 10 10 10 10 
## randomforest iteration 32 of 55 cells
## test set size iteration 33 : 5 5 5 5 5 5 10 
## randomforest iteration 33 of 36 cells
## test set size iteration 34 : 10 10 10 10 10 10 10 
## randomforest iteration 34 of 56 cells
## test set size iteration 35 : 10 10 10 10 10 10 10 
## randomforest iteration 35 of 55 cells
## test set size iteration 36 : 10 10 10 10 10 10 10 
## randomforest iteration 36 of 55 cells
## test set size iteration 37 : 10 10 10 10 10 10 10 
## randomforest iteration 37 of 54 cells
## test set size iteration 38 : 10 10 10 10 10 10 10 
## randomforest iteration 38 of 56 cells
## test set size iteration 39 : 10 10 10 10 10 10 10 
## randomforest iteration 39 of 58 cells
## test set size iteration 40 : 10 10 10 10 10 10 10 
## randomforest iteration 40 of 47 cells
## test set size iteration 41 : 10 10 10 10 10 10 10 
## randomforest iteration 41 of 44 cells
## test set size iteration 42 : 10 10 10 10 10 10 10 
## randomforest iteration 42 of 30 cells
## test set size iteration 43 : 10 10 10 10 10 10 10 
## randomforest iteration 43 of 18 cells
## test set size iteration 44 : 10 10 10 10 10 10 10 
## randomforest iteration 44 of 2 cells

Extract the Nr4a2 and Nfix “lineage” cells

Aligne cells along Pseudotime

We decided to use spring space dimensionality reduction to fit the principale curve because it has been calculated on all cells together. Thus reflecting pan neuronal differentiation axis of varation.

Find DEG between the two trajectories and along the pseudotime

Find direction of the DEG

We find direction of the DEG by calculating the area between curves (ABC) for branch-dependent genes by adapting the monocle package function calABCs. Genes specific ABC is computed on smoothed expression value over 100 points along the pseudotime

Cluster genes by expression profiles along the two trajectories

Nr4a2 neurons specific transcriptional trajectories

Manuscript Fig. 7D

Manuscript Fig. 7D

Nfix neurons specific transcriptional trajectories

Manuscript Fig. 7C

Manuscript Fig. 7C

Session Info

## [1] "04 novembre, 2020, 10,41"
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
## LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
##  [1] splines   stats4    parallel  stats     graphics  grDevices utils    
##  [8] datasets  methods   base     
## 
## other attached packages:
##  [1] wesanderson_0.3.6   RColorBrewer_1.1-2  patchwork_0.0.1    
##  [4] ggExtra_0.9         reshape2_1.4.3      dplyr_0.8.3        
##  [7] FateID_0.1.9        monocle_2.14.0      DDRTree_0.1.5      
## [10] irlba_2.3.3         VGAM_1.1-2          Biobase_2.46.0     
## [13] BiocGenerics_0.32.0 princurve_2.1.4     Seurat_2.3.4       
## [16] Matrix_1.2-17       cowplot_1.0.0       ggplot2_3.2.1      
## 
## loaded via a namespace (and not attached):
##   [1] snow_0.4-3           backports_1.1.5      Hmisc_4.3-0         
##   [4] plyr_1.8.4           igraph_1.2.5         lazyeval_0.2.2      
##   [7] densityClust_0.3     lle_1.1              fastICA_1.2-2       
##  [10] digest_0.6.25        foreach_1.4.7        htmltools_0.5.0     
##  [13] viridis_0.5.1        lars_1.2             gdata_2.18.0        
##  [16] magrittr_1.5         checkmate_1.9.4      cluster_2.1.0       
##  [19] mixtools_1.1.0       ROCR_1.0-7           limma_3.42.0        
##  [22] matrixStats_0.55.0   R.utils_2.9.0        docopt_0.6.1        
##  [25] askpass_1.1          colorspace_1.4-1     ggrepel_0.8.1       
##  [28] xfun_0.18            sparsesvd_0.2        crayon_1.3.4        
##  [31] jsonlite_1.7.0       zeallot_0.1.0        survival_2.44-1.1   
##  [34] zoo_1.8-6            iterators_1.0.12     ape_5.3             
##  [37] glue_1.4.1           gtable_0.3.0         kernlab_0.9-29      
##  [40] prabclus_2.3-1       DEoptimR_1.0-8       scales_1.1.0        
##  [43] pheatmap_1.0.12      som_0.3-5.1          bibtex_0.4.2        
##  [46] miniUI_0.1.1.1       Rcpp_1.0.5           metap_1.1           
##  [49] dtw_1.21-3           xtable_1.8-4         viridisLite_0.3.0   
##  [52] htmlTable_1.13.2     reticulate_1.13      foreign_0.8-72      
##  [55] bit_4.0.4            proxy_0.4-23         mclust_5.4.5        
##  [58] SDMTools_1.1-221.1   Formula_1.2-3        tsne_0.1-3          
##  [61] umap_0.2.3.1         htmlwidgets_1.5.1    httr_1.4.1          
##  [64] FNN_1.1.3            gplots_3.0.1.1       fpc_2.2-3           
##  [67] acepack_1.4.1        modeltools_0.2-22    ica_1.0-2           
##  [70] farver_2.0.1         pkgconfig_2.0.3      R.methodsS3_1.7.1   
##  [73] flexmix_2.3-15       nnet_7.3-14          locfit_1.5-9.1      
##  [76] labeling_0.3         later_1.0.0          tidyselect_0.2.5    
##  [79] rlang_0.4.7          munsell_0.5.0        tools_3.6.3         
##  [82] ggridges_0.5.1       fastmap_1.0.1        evaluate_0.14       
##  [85] stringr_1.4.0        yaml_2.2.1           npsurv_0.4-0        
##  [88] knitr_1.26           bit64_4.0.2          fitdistrplus_1.0-14 
##  [91] robustbase_0.93-5    caTools_1.17.1.2     randomForest_4.6-14 
##  [94] purrr_0.3.3          RANN_2.6.1           pbapply_1.4-2       
##  [97] nlme_3.1-141         mime_0.7             slam_0.1-46         
## [100] R.oo_1.23.0          hdf5r_1.3.2.9000     compiler_3.6.3      
## [103] rstudioapi_0.11      png_0.1-7            lsei_1.2-0          
## [106] tibble_2.1.3         stringi_1.4.6        highr_0.8           
## [109] lattice_0.20-41      HSMMSingleCell_1.6.0 vctrs_0.2.0         
## [112] pillar_1.4.2         lifecycle_0.1.0      combinat_0.0-8      
## [115] Rdpack_0.11-0        lmtest_0.9-37        data.table_1.12.6   
## [118] bitops_1.0-6         gbRd_0.4-11          httpuv_1.5.2        
## [121] R6_2.4.1             latticeExtra_0.6-28  promises_1.1.0      
## [124] KernSmooth_2.23-15   gridExtra_2.3        codetools_0.2-16    
## [127] MASS_7.3-53          gtools_3.8.1         assertthat_0.2.1    
## [130] openssl_1.4.1        withr_2.1.2          qlcMatrix_0.9.7     
## [133] diptest_0.75-7       doSNOW_1.0.18        grid_3.6.3          
## [136] rpart_4.1-15         tidyr_1.0.0          class_7.3-17        
## [139] rmarkdown_2.5        segmented_1.0-0      Rtsne_0.15          
## [142] shiny_1.4.0          snowfall_1.84-6.1    scatterplot3d_0.3-41
## [145] base64enc_0.1-3

  1. Institute of Psychiatry and Neuroscience of Paris, INSERM U1266, 75014, Paris, France

LS0tCnRpdGxlOiAiQ29tcGFyYWlzb24gb2YgVlAgYW5kIERQIGRlcml2ZWQgbmV1cm9ucyBkaWZmZXJlbnRpYXRpb24gdHJhamVjdG9yaWVzIgphdXRob3I6CiAgLSBNYXR0aGlldSBNb3JlYXVeW0luc3RpdHV0ZSBvZiBQc3ljaGlhdHJ5IGFuZCBOZXVyb3NjaWVuY2Ugb2YgUGFyaXMsIElOU0VSTSBVMTI2NiwgNzUwMTQsIFBhcmlzLCBGcmFuY2VdLCBtYXR0aGlldS5tb3JlYXVAaW5zZXJtLmZyCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OiAKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgZGZfcHJpbnQ6IHRpYmJsZQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICBpbmNsdWRlczoKICAgICAgaW5faGVhZGVyOiBoZWFkZXIuaHRtbAogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKYGBge2NzcywgZWNobz1GQUxTRX0KaDEgewogIGZvbnQtc2l6ZTogMzRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICNlNjRkMDA7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CmgxLnRpdGxlIHsKICBmb250LXNpemU6IDQwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDIgewogIGZvbnQtc2l6ZTogMzBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDMgewogIGZvbnQtc2l6ZTogMjRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDQgewogIGZvbnQtc2l6ZTogMjBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDUgewogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KCi5zY3JvbGwtMTAwIHsKICBtYXgtaGVpZ2h0OiAyMDBweDsKICBvdmVyZmxvdy15OiBhdXRvOwogIGJhY2tncm91bmQtY29sb3I6IGluaGVyaXQ7Cn0KCnAgewogIGZvbnQtc2l6ZTogMTZweDsKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFKQpgYGAKCiMgTG9hZCBsaWJyYXJpZXMgYW5kIFFDRmlsdGVyZWQgZGF0YXNldAoKYGBge3IgfQojIExvYWQgbGlicmFyeQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShwcmluY3VydmUpCmxpYnJhcnkobW9ub2NsZSkKbGlicmFyeShGYXRlSUQpCmxpYnJhcnkocGFyYWxsZWwpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KGdnRXh0cmEpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeSh3ZXNhbmRlcnNvbikKCiNTZXQgZ2dwbG90IHRoZW1lIGFzIGNsYXNzaWMKdGhlbWVfc2V0KHRoZW1lX2NsYXNzaWMoKSkKYGBgCgpgYGB7cn0KIyBMb2FkIHRoZSBmdWxsIGFubm90YXRlZCBkYXRhc2V0CkFsbGNlbGxzLmRhdGEgPC0gcmVhZFJEUygiLi9DbHVzdGVyZWQuY2VsbHMuUkRTIikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOCwgNil9CmNvbG9ycyA8LSAgYygiIzk2OTY5NiIsCiAgICAgICAgICAgICAgdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjODNDM0I4IiwgIiMwMDlGREEiLCAiIzNFNjlBQyIsICIjRTQ2QjZCIikpLAogICAgICAgICAgICAgICIjZWM3NTZkIiwgIiNjNzczYTciLCAiIzcyOTNjOCIsICIjYjc5ZjBiIiwgIiMzY2E3M2YiLCIjMzFiNmJkIiwKICAgICAgICAgICAgICAiI2ViY2IyZSIsICIjOWVjMjJmIiwgIiNhOTk2MWIiLCAiI2NjM2ExYiIsICIjY2M4Nzc4IiAsICIjZDE0YzhkIiwgIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiwiI2U2YmI5YiIsICIjMDQ2YzlhIiwgIiM0Nzg0YTIiICwgIiM0OTkwYzkiKQoKRGltUGxvdChBbGxjZWxscy5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwgCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSAyLAogICAgICAgIG5vLmxlZ2VuZCA9IEYsCiAgICAgICAgY29scy51c2UgPSBjb2xvcnMpCmBgYAoKIyBQYWxsaWFsIHRyYW5zaXRpb24gc3RhdGUgY2VsbHMKCiMjIEV4dHJhY3QgYXBpY2FsIHByb2dlbml0b3JzCgpXZSBwZXJmb3JtIEttZWFucyBjbHVzdGVyaW5nIG9uIHRoZSA0IGNlbGwgc3RhdGUgc2NvcmVzIDoKCi0gU3ViLXBhbGxpYWwgbmV1cm9ucyBgU1BgCi0gUGFsbGlhbCBuZXVyb25zIGBQYWxgCi0gU3ViLXBhbGxpYWwgQlAgYFNQLkJQYAotIFBhbGxpYWwgQlAgYFBhbC5CUGAKCmBgYHtyfQojQ2FsY3VsYXRlIFBhbGxpYWwgYW5kIFN1Yi1wYWxsaWFsIEJQIHNjb3JlcwpQYWwuQlAuZ2VuZXMgPC0gYygiRW9tZXMiLCAiTmV1cm9nMiIsICJOZXVyb2cxIiwgIlBybXQ4IiwgIk5ycDEiKQpnZW5lcy5saXN0IDwtIGxpc3QoUGFsLkJQLmdlbmVzKQplbnJpY2gubmFtZSA8LSAiUGFsLkJQX3NpZ25hdHVyZSIKQWxsY2VsbHMuZGF0YSA8LSBBZGRNb2R1bGVTY29yZShBbGxjZWxscy5kYXRhLCBnZW5lcy5saXN0ID0gZ2VuZXMubGlzdCwgZ2VuZXMucG9vbCA9IE5VTEwsIG4uYmluID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkLnVzZSA9IDEsIGN0cmwuc2l6ZSA9IGxlbmd0aChnZW5lcy5saXN0KSwgdXNlLmsgPSBGQUxTRSwgZW5yaWNoLm5hbWUgPSBlbnJpY2gubmFtZSAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tLnNlZWQgPSAxKQoKClNQLkJQLmdlbmVzIDwtIGMoIkRseDEiLCAiRGx4MiIsICJEbHg1IiwiQXNjbDEiLCAiR3N4MiIpCmdlbmVzLmxpc3QgPC0gbGlzdChTUC5CUC5nZW5lcykKZW5yaWNoLm5hbWUgPC0gIlNQLkJQX3NpZ25hdHVyZSIKQWxsY2VsbHMuZGF0YSA8LSBBZGRNb2R1bGVTY29yZShBbGxjZWxscy5kYXRhLCBnZW5lcy5saXN0ID0gZ2VuZXMubGlzdCwgZ2VuZXMucG9vbCA9IE5VTEwsIG4uYmluID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkLnVzZSA9IDEsIGN0cmwuc2l6ZSA9IGxlbmd0aChnZW5lcy5saXN0KSwgdXNlLmsgPSBGQUxTRSwgZW5yaWNoLm5hbWUgPSBlbnJpY2gubmFtZSAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tLnNlZWQgPSAxKQpgYGAKCmBgYHtyfQpzZXQuc2VlZCgxMDApCiMgUnVuIEttZWFucyBjbHVzdGVyaW5nCmNsIDwtIGttZWFucyhjYmluZChBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRTUF9zaWduYXR1cmUxLAogICAgICAgICAgICAgICAgICAgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkUGFsX3NpZ25hdHVyZTEsCiAgICAgICAgICAgICAgICAgICBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRTUC5CUF9zaWduYXR1cmUxLAogICAgICAgICAgICAgICAgICAgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkUGFsLkJQX3NpZ25hdHVyZTEpLCA0KQoKQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEka21lYW5DbHVzdCA8LSBwYXN0ZTAoIkNsdXN0LiIsY2wkY2x1c3RlcikKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KX0KY29sLnBhbCA8LSB3ZXNfcGFsZXR0ZSgiR3JhbmRCdWRhcGVzdDEiLCA0LCB0eXBlID0gImRpc2NyZXRlIikKCnAxIDwtIGdncGxvdChBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSwgYWVzKHg9U1Bfc2lnbmF0dXJlMSwgeT1QYWxfc2lnbmF0dXJlMSwgY29sb3VyID0ga21lYW5DbHVzdCkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWNvbC5wYWwpICsKICBnZW9tX3BvaW50KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpnZ01hcmdpbmFsKHAxLCB0eXBlID0gImhpc3RvZ3JhbSIsIGZpbGw9ImxpZ2h0Z3JleSIpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAia21lYW5DbHVzdCIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGNvbHMudXNlID0gY29sLnBhbCwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8ubGVnZW5kID0gRikKYGBgCgpXZSB0aGVuIGV4dHJhY3QgdGhlIFBhbGxpYWwgY2VsbHMgYnJhbmNoZS4gV2UgYWxzbyBleGNsdWRlcyBDUiBjZWxscyBjbHVzdGVyIGZvcm0gdGhlIHRyYWplY3RvcnkgaW5mZXJlbmNlLgoKYGBge3J9CiNSZW1vdmUgdGhlIHN1Yi1wYWxsaWFsIGNlbGxzIGJyYW5jaGUKTWVhbktjbHVzdC5TUHNjb3JlIDwtIGFnZ3JlZ2F0ZShTUF9zaWduYXR1cmUxIH4ga21lYW5DbHVzdCwgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEsIG1lYW4pClNQY2x1c3QgPC0gTWVhbktjbHVzdC5TUHNjb3JlICU+JSBmaWx0ZXIoU1Bfc2lnbmF0dXJlMSA9PSBtYXgoU1Bfc2lnbmF0dXJlMSkpICU+JSBwdWxsKGttZWFuQ2x1c3QpCgpTUC5jZWxscyA8LSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSAlPiUgZmlsdGVyKGttZWFuQ2x1c3QgPT0gU1BjbHVzdCkgJT4lIHB1bGwoQmFyY29kZXMpCgojIFJlbW92ZSBjZWxscyBub3QgdXNlIGZvciB0cmFqZWN0b3J5IGluZmVyZW5jZSAoU3VicGFsbGlhbCBjZWxscyBkZWZpbmVkIGJ5IGttZWFucywgTGF0ZSBHQUJBIG5ldXJvbnMgYW5kIENSIGNlbGxzKQpFeGNsdWRlZC5jbHVzdGVycyA8LSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSAlPiUKICAgICAgICAgICAgICAgICAgZmlsdGVyKENsdXN0ZXIuaWRlbnQgJWluJSBncmVwKCIqU3VifEdBQkF8TE4uR2x1dC4xM3xMTi5HbHV0LjE0fExOLkdsdXQuMSQiLCB1bmlxdWUoYXMuY2hhcmFjdGVyKEFsbGNlbGxzLmRhdGFAaWRlbnQpKSwgdmFsdWUgPSBUKSkgJT4lCiAgICAgICAgICAgICAgICAgIHB1bGwoQmFyY29kZXMpIAoKIyBXZSBmdXJ0aGVyIGtlZXAgb25seSBwYWxsaWFsIGFwaWNhbCBwcm9nZW5pdG9yIGNsdXN0ZXIgYW1vbmcgb3RoZXIgQVAgY2x1c3RlcnMKTWVhbktjbHVzdC5BUHNjb3JlIDwtIGFnZ3JlZ2F0ZShBUF9zaWduYXR1cmUxIH4ga21lYW5DbHVzdCwgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEsIG1lYW4pCkFQY2x1c3QgPC0gTWVhbktjbHVzdC5BUHNjb3JlICU+JSBmaWx0ZXIoQVBfc2lnbmF0dXJlMSA9PSBtYXgoQVBfc2lnbmF0dXJlMSkpICU+JSBwdWxsKGttZWFuQ2x1c3QpCgpBbGwuQVAgPC0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEgJT4lIGZpbHRlcihrbWVhbkNsdXN0ID09IEFQY2x1c3QpICU+JSBwdWxsKEJhcmNvZGVzKQpWYWxpZGUuQVAgPC0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEgJT4lIGZpbHRlcihDbHVzdGVyLmlkZW50ICVpbiUgZ3JlcCgiRG9yc2FsLlBhbGxpdW18bGF0ZXJhbC5QYWxsaXVtLjF8bGF0ZXJhbC5QYWxsaXVtLjJ8VmVudHJhbC5QYWxsaXVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pcXVlKGFzLmNoYXJhY3RlcihBbGxjZWxscy5kYXRhQGlkZW50KSksIHZhbHVlID0gVCkpICU+JSBwdWxsKEJhcmNvZGVzKQoKZmlsdGVyZWQuQVAgPC0gQWxsLkFQWyFBbGwuQVAgJWluJSBWYWxpZGUuQVBdCgojUmVtb3ZlIGFsbCBpbnZhbGlkZSBjZWxscyArIDMgcGFsbGlhbCBvdXRsaWVyIGNlbGxzCkNlbGxzLnRvLnVzZSA8LSByb3duYW1lcyhBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSlbIXJvd25hbWVzKEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhKSAlaW4lIHVuaXF1ZShjKFNQLmNlbGxzLCBFeGNsdWRlZC5jbHVzdGVycywgZmlsdGVyZWQuQVAsIGMoIkFUVFRDVEdDQUNHR0NDQVQiICwgIkNBQUdUVEdDQUFHQ0NUQVQiLCAiQ1RBQ0FUVEdUQUdDVEdDQyIpKSldCkFsbGNlbGxzLmRhdGEgPC0gU3Vic2V0RGF0YShBbGxjZWxscy5kYXRhLCBjZWxscy51c2UgPSBDZWxscy50by51c2UsIHN1YnNldC5yYXcgPSBULCAgZG8uY2xlYW4gPSBGKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg4LCA2KX0KY29sb3JzIDwtICBjKCIjOTY5Njk2IiwKICAgICAgICAgICAgICB0b2xvd2VyKGMoIiM2OEIwNDEiLCAiI0UzQzE0OCIsICIjQjdEMTc0IiwgIiNFNDZCNkIiKSksCiAgICAgICAgICAgICAgIiNjYzNhMWIiLCAiI2NjODc3OCIgLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIsIiNlNmJiOWIiLCAiIzA0NmM5YSIsICIjNDc4NGEyIiAsICIjNDk5MGM5IikKCkRpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsIAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gMiwKICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgIGNvbHMudXNlID0gY29sb3JzKQpgYGAKCiMjIEZpbHRlciB0aGUgZ2VuZSBjb3VudHMgbWF0cml4CgpgYGB7cn0KIyBGaWx0ZXIgZ2VuZXMKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhBbGxjZWxscy5kYXRhQHJhdy5kYXRhID4gMCkKZ2VuZXMudXNlIDwtIG5hbWVzKHggPSBudW0uY2VsbHNbd2hpY2goeCA9IG51bS5jZWxscyA+PSAyMCldKQpBbGxjZWxscy5kYXRhQHJhdy5kYXRhIDwtIEFsbGNlbGxzLmRhdGFAcmF3LmRhdGFbZ2VuZXMudXNlLCBdCgojIE5vcm1hbGl6YXRpb24gYW5kIHZhcmlhYmxlIGdlbmUgc2VsZWN0aW9uCkFsbGNlbGxzLmRhdGEgPC0gTm9ybWFsaXplRGF0YShvYmplY3QgPSBBbGxjZWxscy5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZS5mYWN0b3IgPSByb3VuZChtZWRpYW4oQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkblVNSSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheS5wcm9ncmVzcyA9IEYpCgpBbGxjZWxscy5kYXRhIDwtIEZpbmRWYXJpYWJsZUdlbmVzKG9iamVjdCA9IEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbi5mdW5jdGlvbiA9IEV4cE1lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGVyc2lvbi5mdW5jdGlvbiA9IExvZ1ZNUiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4Lmxvdy5jdXRvZmYgPSAwLjAzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHguaGlnaC5jdXRvZmYgPSA0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkuY3V0b2ZmID0gMiwgZG8ucGxvdCA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheS5wcm9ncmVzcyA9IEYpCmxlbmd0aChBbGxjZWxscy5kYXRhQHZhci5nZW5lcykKYGBgCgoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgIkFsbGNlbGxzLmRhdGEiXSkKYGBgCgojIENvbXB1dGUgY2VsbHMnIGZhdGUgYmlhcyBhbG9uZyB0cHdhcmQgZWFjaCBtYXR1cmUgbmV1cm9uYWwgdHlwZXMKCiMjIFByZXBhcmUgRmF0ZUlEIGlucHV0IGRhdGEKCmBgYHtyfQojIEZhdGFJRCByZXF1aWVyZXMgdGhlIHRlcm1pbmFsIGNsdXN0ZXJzIElEIHRvIGJlIGludGVnZXJzClRlcm1pbmFsRmF0ZXMgPC0gZ3JlcCgiMTZ8MjR8MjJ8MTl8MjZ8MjB8MjEiLCB1bmlxdWUoYXMuY2hhcmFjdGVyKEFsbGNlbGxzLmRhdGFAaWRlbnQpKSwgdmFsdWUgPSBUKQoKQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkTmV3Q2x1c3RlcklEIDwtIHNhcHBseShhcy5jaGFyYWN0ZXIoQWxsY2VsbHMuZGF0YUBpZGVudCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkgaWYoeCA9PSBUZXJtaW5hbEZhdGVzWzFdKXt4PTF9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZih4PT0gVGVybWluYWxGYXRlc1syXSl7eD0yfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoeD09IFRlcm1pbmFsRmF0ZXNbM10pe3g9M30KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKHg9PSBUZXJtaW5hbEZhdGVzWzRdKXt4PTR9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZih4PT0gVGVybWluYWxGYXRlc1s1XSl7eD01fQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoeD09IFRlcm1pbmFsRmF0ZXNbNl0pe3g9Nn0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKHg9PSBUZXJtaW5hbEZhdGVzWzddKXt4PTd9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZXt4PXh9KQpBbGxjZWxscy5kYXRhIDwtIFNldEFsbElkZW50KEFsbGNlbGxzLmRhdGEsIGlkID0gIk5ld0NsdXN0ZXJJRCIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDgsIDYpfQpjb2xvcnMgPC0gIGMoIiNjYzg3NzgiICwgIiNkMTRjOGQiLCAiIzRjYWJkYyIsICIjNWFiNzkzIiwgIiNlNzgyM2EiLCIjZTZiYjliIiwiI2NjM2ExYiIsCiAgICAgICAgICAgICAiIzk2OTY5NiIsCiAgICAgICAgICAgICAgdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjRTQ2QjZCIikpLAogICAgICAgICAgICAgICIjMDQ2YzlhIiwgIiM0Nzg0YTIiICwgIiM0OTkwYzkiKQoKRGltUGxvdChBbGxjZWxscy5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwgCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmxlZ2VuZCA9IFQsCiAgICAgICAgY29scy51c2UgPSBjb2xvcnMpCmBgYAoKV2UgcmVzdHJpY3RlZCB0aGUgYW5hbHlzaXMgdG8gdGhlIG1vc3QgdmFyaWFibGUgZ2VuZXMgYXMgZGVydGVybWluZWQgYnkgdGhlIFNldXJhdCBmdW5jdGlvbiAiRmluZFZhcmlhYmxlR2VuZXMiIGV4Y2x1ZGluZyBjZWxsIGN5bGNlIHBoYXNlIGdlbmVzCgpgYGB7cn0KIyBFeGNsdWRlIGNlbGwgY3ljbGUgYXNzb2NpYXRlZCBnZW5lcwpDQ2dlbmVzIDwtIGFzLmNoYXJhY3RlcihyZWFkLnRhYmxlKCIuL1Byb2dlbml0b3JzL0NlbGxDeWNsZUdlbmVzLmNzdiIsIHNlcCA9ICJcdCIsIGhlYWRlciA9IEYpWywxXSkKSW5wdXQuZ2VuZXMgPC0gQWxsY2VsbHMuZGF0YUB2YXIuZ2VuZXNbIUFsbGNlbGxzLmRhdGFAdmFyLmdlbmVzICVpbiUgQ0NnZW5lc10KCiMgRmF0ZUlEIHJlcXVpZXJlcyB0aGUgZXhwcmVzc2lvbiBtYXRyaXggdG8gYmUgYSBkYXRhZnJhbWUKTm9ybS5NYXQgPC0gYXMuZGF0YS5mcmFtZShhcy5tYXRyaXgoQWxsY2VsbHMuZGF0YUBkYXRhW3Jvdy5uYW1lcyhBbGxjZWxscy5kYXRhQGRhdGEpICVpbiUgSW5wdXQuZ2VuZXMsXSkpCgojIFNldCBhIGNsdXN0ZXIgYXNzaWdubWVudCBmYWN0b3IgZm9yIGVhY2ggY2VsbHMKQ2x1c3RlcklkZW50IDwtIGFzLmNoYXJhY3RlcihBbGxjZWxscy5kYXRhQGlkZW50KQpuYW1lcyhDbHVzdGVySWRlbnQpIDwtIG5hbWVzKEFsbGNlbGxzLmRhdGFAaWRlbnQpCgojIEZpbmFseSBGYXRlSUQgcmVxdWlyZXMgdG8gc3BlY2lmeSB0aGUgaWRlbnRpdHkgb2YgdGhlIGF0dHJhY3RvciBzdGF0ZSBjbHVzdGVycwpBdHRyYWN0b3JzIDwtIDE6NwpgYGAKCiMjIENvbXB0ZSB0aGUgY2VsbHMnIGZhdGUgYmlhcwoKYGBge3IgY2xhc3Mub3V0cHV0PSJzY3JvbGwtMTAwIn0KSW5mZXJlZC5GYXRlLmJpYXMgIDwtIGZhdGVCaWFzKE5vcm0uTWF0LCBDbHVzdGVySWRlbnQsIEF0dHJhY3RvcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6ID0gMS1jb3IoTm9ybS5NYXQsIG1ldGhvZCA9ICJzcGVhcm1hbiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlubnI9MTAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5ucmg9MzAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGFwdD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlkZW5jZT0wLjk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmJmYWN0b3I9NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZS5kaXN0PUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZD0xMjM0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmJ0cmVlPU5VTEwpCmBgYAojIyMgSW5zcGVjdCB0aGUgdHJhaW5uaW5nIHNldCB1c2UgYXQgZWFjaCBjbGFzc2lmaWNhdGlvbiBpdGVyYXRpb24KYGBge3J9CkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJEZhdGVJRC5pdGVyYXRpb24gPC0gIjAiCkFsbGNlbGxzLmRhdGEgPC0gU2V0QWxsSWRlbnQoQWxsY2VsbHMuZGF0YSwgaWQgPSAiRmF0ZUlELml0ZXJhdGlvbiIpCgpmb3IgKGkgaW4gc2VxKDAsIGxlbmd0aChJbmZlcmVkLkZhdGUuYmlhcyRyZmwpLCBieSA9IDUpWy0xXSkgewogIGl0ZXIgPC0gc2VxKGktNCxpKQogIEJhcmNvZGVzIDwtIGMoKQogIGZvciAoaiBpbiBpdGVyKSB7CiAgICBCYXJjb2RlcyA8LSBjKEJhcmNvZGVzLCBuYW1lcyhJbmZlcmVkLkZhdGUuYmlhcyRyZmxbW2pdXSRwcmVkaWN0ZWQpKQogIH0KICBBbGxjZWxscy5kYXRhIDwtIFNldElkZW50KEFsbGNlbGxzLmRhdGEsIGNlbGxzLnVzZSA9IEJhcmNvZGVzLCBpZGVudC51c2UgPSBwYXN0ZTAoIml0ZXIgIixpdGVyWzFdLCIgdG8gIiwgaXRlcls0XSkpCn0KYGBgCgoKYGBge3IgZmlnLmRpbT1jKDgsIDYpfQpjb2xvcnMgPC0gYygiI2QxNGM4ZCIsICIjY2MzYTFiIiwgIiMwNDZjOWEiLCAiI2U3ODIzYSIsICIjY2M4Nzc4IiwgIiM2OGIwNDEiLCAiIzVhYjc5MyIsICIjZTNjMTQ4IiwgIiNlNDZCNmIiLCAiI2I3OWYwYiIpCkRpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgZGltLjEgPSAxLGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIG5vLmxlZ2VuZCA9IEYsCiAgICAgICAgY29scy51c2UgPSBjKCIjZGZkZmRmIiwgY29sb3JzKSkKYGBgCgojIyMgSW5zcGVjdCB0aGUgdGVzdCBzZXQgdXNlIGF0IGNsYXNzaWZpY2F0aW9uIGl0ZXJhdGlvbgpgYGB7cn0KQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkRmF0ZUlELml0ZXJhdGlvbiA8LSAiMCIKQWxsY2VsbHMuZGF0YSA8LSBTZXRBbGxJZGVudChBbGxjZWxscy5kYXRhLCBpZCA9ICJGYXRlSUQuaXRlcmF0aW9uIikKCmZvciAoaSBpbiBzZXEoMCwgbGVuZ3RoKEluZmVyZWQuRmF0ZS5iaWFzJHJmbCksIGJ5ID0gNSlbLTFdKSB7CiAgaXRlciA8LSBzZXEoaS00LGkpCiAgQmFyY29kZXMgPC0gYygpCiAgZm9yIChqIGluIGl0ZXIpIHsKICAgIEJhcmNvZGVzIDwtIGMoQmFyY29kZXMsIG5hbWVzKEluZmVyZWQuRmF0ZS5iaWFzJHJmbFtbal1dJHRlc3QkcHJlZGljdGVkKSkKICB9CiAgQWxsY2VsbHMuZGF0YSA8LSBTZXRJZGVudChBbGxjZWxscy5kYXRhLCBjZWxscy51c2UgPSBCYXJjb2RlcywgaWRlbnQudXNlID0gcGFzdGUwKCJpdGVyICIsaXRlclsxXSwiIHRvICIsIGl0ZXJbNF0pKQp9CmBgYAoKCmBgYHtyIGZpZy5kaW09Yyg4LCA2KX0KRGltUGxvdChBbGxjZWxscy5kYXRhLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICBkaW0uMSA9IDEsZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgbm8ubGVnZW5kID0gRiwKICAgICAgICBjb2xzLnVzZSA9IGMoIiNkZmRmZGYiLCBjb2xvcnMpKQoKQWxsY2VsbHMuZGF0YSA8LSBTZXRBbGxJZGVudChBbGxjZWxscy5kYXRhLCBpZCA9ICJDbHVzdGVyLmlkZW50IikKYGBgCgojIyBJbXBvcnQgbGluZWFnZSBiaWFzIGludG8gU2V1cmF0IG1ldGEuZGF0YQoKYGBge3J9CnByb2JzIDwtIEluZmVyZWQuRmF0ZS5iaWFzJHByb2JzWyxzZXEobGVuZ3RoKEF0dHJhY3RvcnMpKV0KCkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuTnI0YTIgPC0gcHJvYnMkdDEKQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkcHJvYi5Gb3hwMmMgPC0gcHJvYnMkdDIKQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkcHJvYi5QcHAxcjE0YyA8LSBwcm9icyR0MwpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLkZlemYxIDwtIHByb2JzJHQ0CkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuRm94cDJhIDwtIHByb2JzJHQ1CkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuRm94cDJiIDwtIHByb2JzJHQ2CkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuTmZpeCA8LSBwcm9icyR0NwpgYGAKCmBgYHtyIGZpZy5kaW09Yyg5LCA5KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA3QSBhbmQgUzdBIn0KRmVhdHVyZVBsb3Qob2JqZWN0ID0gQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgZmVhdHVyZXMucGxvdCA9IGMoInByb2IuTnI0YTIiLCAicHJvYi5OZml4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInByb2IuUHBwMXIxNGMiLCJwcm9iLkZlemYxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInByb2IuRm94cDJhIiwgInByb2IuRm94cDJiIiwgInByb2IuRm94cDJjIiksCiAgICAgICAgICAgIGNvbHMudXNlID0gcmV2KFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbChuID0gMTEsIG5hbWUgPSAiU3BlY3RyYWwiKSksCiAgICAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICAgICAgbm8ubGVnZW5kID0gVCkKYGBgCgojIEV4dHJhY3QgdGhlIE5yNGEyIGFuZCBOZml4ICJsaW5lYWdlIiBjZWxscwoKIyMgRmluZCBjZWxscyB3aXRoIHN0cm9uZyBiaWFzZSB0b3dhcmQgTnI0YTIgbmV1cm9ucwoKYGBge3J9CkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJE5yNGEyLmJpYXNlIDwtIGlmZWxzZShBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLk5yNGEyID4gMC41ICYgYWJzKEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuTmZpeC0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkcHJvYi5OcjRhMikgPiAwLjI1LCAiTnI0YTIubGluZWFnZSIsICJPdGhlci5saW5lYWdlcyIgKQoKdGFibGUoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkTnI0YTIuYmlhc2UpCmBgYAoKCiMjIEZpbmQgY2VsbHMgd2l0aCBzdHJvbmcgYmlhc2UgdG93YXJkIE5maXggbmV1cm9ucwoKYGBge3J9CkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJE5maXguYmlhc2UgPC0gaWZlbHNlKEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuTmZpeCA+IDAuNSAmIGFicyhBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLk5maXgtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuTnI0YTIpID4gMC4yNSwgIk5maXgubGluZWFnZSIsICJPdGhlci5saW5lYWdlcyIgKQoKdGFibGUoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkTmZpeC5iaWFzZSkKYGBgCgpgYGB7ciBmaWcuZGltPWMoMTYsIDYpfQpwMSA8LSBEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAiTnI0YTIuYmlhc2UiLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgY29scy51c2UgPSBjKCIjMDI2YzlhIiwiI2RmZGZkZiIpLAogICAgICAgIG5vLmxlZ2VuZCA9IFQsCiAgICAgICAgZG8ucmV0dXJuID0gVCkKCnAyIDwtIERpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICBncm91cC5ieSA9ICJOZml4LmJpYXNlIiwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIGNvbHMudXNlID0gYygiI2NjMzkxYiIsIiNkZmRmZGYiKSwKICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgIGRvLnJldHVybiA9IFQpCgpwMSArIHAyCmBgYAoKIyMgSW5zcGVjdCBmYXRlIGJpYXMgYW1vbmcgQVBzCgpgYGB7cn0KIyBGYXRlIGJpYXNlIGluIHByb2dlbml0b3IgZG9tYWluZXMKZGF0YSA8LSBtZWx0KGRhdGEuZnJhbWUoQ2x1c3RlcnMgPSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRDbHVzdGVyLmlkZW50LAogICAgICAgICAgICAgICAgICAgICAgICBOZml4LnNjb3JlID0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkcHJvYi5OZml4LAogICAgICAgICAgICAgICAgICAgICAgICBOcjRhMi5zY29yZSA9IEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuTnI0YTIpKQoKY29sbmFtZXMoZGF0YSkgPC0gYygiQ2x1c3RlcnMiLCAibGluZWFnZSIsICJTY29yZSIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDYsIDQuNSl9CmRhdGEgJT4lCiAgICAgZmlsdGVyKENsdXN0ZXJzICVpbiUgYygiQVAuVmVudHJhbC5QYWxsaXVtIiwgIkFQLmxhdGVyYWwuUGFsbGl1bS4xIiwgIkFQLmxhdGVyYWwuUGFsbGl1bS4yIiwgIkFQLkRvcnNhbC5QYWxsaXVtIikpICU+JQogICAgIG11dGF0ZShDbHVzdGVycyA9IGZhY3RvcihDbHVzdGVycywgbGV2ZWxzID1jKCJBUC5WZW50cmFsLlBhbGxpdW0iLCAiQVAubGF0ZXJhbC5QYWxsaXVtLjEiLCAiQVAubGF0ZXJhbC5QYWxsaXVtLjIiLCAiQVAuRG9yc2FsLlBhbGxpdW0iKSkpICU+JQogICAgIGdncGxvdChhZXMoeD1mYWN0b3IobGluZWFnZSwgbGV2ZWxzID0gYygiTnI0YTIuc2NvcmUiLCAiTmZpeC5zY29yZSIpICksIHk9U2NvcmUsIGZpbGw9IENsdXN0ZXJzKSkgKyAKICAgICAgICBnZW9tX2JveHBsb3Qobm90Y2g9VFJVRSkgKwogICAgICAgIGdlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4yKSwgc2l6ZSA9IC41LCBhZXMoZ3JvdXA9Q2x1c3RlcnMpKSArCiAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPSBjKCIjNjhiMDQxIiwgIiNlM2MxNDgiLCAiI2I3ZDE3NCIsICIjZTQ2YjZiIikpICArCiAgICAgICAgeGxhYigiIikKYGBgCgojIyBFeHRyYWN0IE5yNGEyIGFuZCBOZml4IGJpYXNlZCBjZWxscwoKYGBge3IgZmlnLmRpbT1jKDgsIDYpfQojU3Vic2V0IGRhdGFzZXQgdG8ga2VlcCBvbmx5IGNlbGxzIHdoaWNoIHNob3dlZCBzdWZmaWNpZW50IGRpZmZlcmVuY2Ugb2YgZmF0ZSBwcm9iYWJpbGl0eQpWUC5EUC5saW5lYWdlLmNlbGxzIDwtIGMocm93bmFtZXMoc3Vic2V0KEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhLCBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSROcjRhMi5iaWFzZSA9PSAiTnI0YTIubGluZWFnZSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKHN1YnNldChBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSwgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkTmZpeC5iaWFzZSA9PSAiTmZpeC5saW5lYWdlIikpKQoKCiMgV2UgZnVydGhlciBvbmx5IHJldGFpbiBWUCBhbmQgRFAgIHByb2dlbml0b3IgY2x1c3RlcnMKQWxsY2VsbHMuZGF0YSA8LSBTdWJzZXREYXRhKEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxscy51c2UgPSBWUC5EUC5saW5lYWdlLmNlbGxzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnQucmVtb3ZlID0gYygiQVAubGF0ZXJhbC5QYWxsaXVtLjEiLCAiQVAubGF0ZXJhbC5QYWxsaXVtLjIiKSAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzZXQucmF3ID0gVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvLmNsZWFuID0gRikKCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICBjb2xzLnVzZSA9IGMoICIjZGZkZmRmIiwiIzY4YjA0MSIsICIjZTQ2YjZiIiwiI2NjM2ExYiIsIiNjYzg3NzgiLCIjZTZiYjliIiAsIiMwNDZjOWEiLCIjNDc4NGEyIiksCiAgICAgICAgbm8ubGVnZW5kID0gVCkKYGBgCgpgYGB7ciBmaWcuZGltPWMoOCwgNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gN0IifQpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRMaW5lYWdlIDwtIGlmZWxzZShBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSROcjRhMi5iaWFzZSA9PSAiTnI0YTIubGluZWFnZSIsICJOcjRhMi5saW5lYWdlIiwgIk5maXgubGluZWFnZSIpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAiTGluZWFnZSIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBjb2xzLnVzZSA9IGMoIiNjYzM5MWIiLCIjMDI2YzlhIiksCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8ubGVnZW5kID0gRikKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJBbGxjZWxscy5kYXRhIildKQpgYGAKCiMgQWxpZ25lIGNlbGxzIGFsb25nIFBzZXVkb3RpbWUKCldlIGRlY2lkZWQgdG8gdXNlIHNwcmluZyBzcGFjZSBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gdG8gZml0IHRoZSBwcmluY2lwYWxlIGN1cnZlIGJlY2F1c2UgaXQgaGFzIGJlZW4gY2FsY3VsYXRlZCBvbiBhbGwgY2VsbHMgdG9nZXRoZXIuIFRodXMgcmVmbGVjdGluZyBwYW4gbmV1cm9uYWwgZGlmZmVyZW50aWF0aW9uIGF4aXMgb2YgdmFyYXRpb24uCgojIyBOcjRhMiBuZXVyb25zIFBzZXVkb3RpbWUgb3JkZXJpbmcKCmBgYHtyfQpOcjRhMi5saW5lYWdlLmNlbGxzIDwtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhICU+JQogICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihMaW5lYWdlID09ICJOcjRhMi5saW5lYWdlIikgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgcHVsbChCYXJjb2RlcykKCiMjIEZpdCBwcmluY2lwYWxlIGN1cnZlIG9uIHRoZSBkYXRhIGluIHRoZSBzcHJpbmcgc3BhY2UKZGF0YS5OcjRhMiA8LSBhcy5kYXRhLmZyYW1lKEFsbGNlbGxzLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1tOcjRhMi5saW5lYWdlLmNlbGxzLDE6Ml0pCgpmaXQgPC0gcHJpbmNpcGFsX2N1cnZlKGFzLm1hdHJpeChkYXRhLk5yNGEyWywxOjJdKSwKICAgICAgICAgICAgICAgICAgICAgICBzbW9vdGhlcj0nc21vb3RoX3NwbGluZScsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJldGNoPTIpCgpOcjRhMi5wYy5saW5lIDwtIGFzLmRhdGEuZnJhbWUoZml0JHNbb3JkZXIoZml0JGxhbWJkYSksXSkgI1RoZSBwcmluY2lwYWwgY3VydmUgc21vb3RoZWQKZGF0YS5OcjRhMiRQc2V1ZG90aW1lU2NvcmUgPC0gZml0JGxhbWJkYS9tYXgoZml0JGxhbWJkYSkKCmRhdGEuTnI0YTIkQ2x1c3RlciA8LSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSAlPiUKICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoTGluZWFnZSA9PSAiTnI0YTIubGluZWFnZSIpICU+JQogICAgICAgICAgICAgICAgICAgICAgIHB1bGwoTmV3Q2x1c3RlcklEKQoKIyBEaXJlY3Rpb24gb2YgdGhlIG1hdHVyYXRpb24gc2NvcmUgdXNpbmcgTmVzIGV4cHJlc3Npb24gKHJldmVydGUgaWYgcG9zaXRpdmUgY29ycmVsYXRpb24pCmlmIChjb3IoZGF0YS5OcjRhMiRQc2V1ZG90aW1lU2NvcmUsIEFsbGNlbGxzLmRhdGFAZGF0YVsnSG1nYTInLCBOcjRhMi5saW5lYWdlLmNlbGxzXSkgPiAwKSB7CiAgZGF0YS5OcjRhMiRQc2V1ZG90aW1lU2NvcmUgPC0gLShkYXRhLk5yNGEyJFBzZXVkb3RpbWVTY29yZSAtIG1heChkYXRhLk5yNGEyJFBzZXVkb3RpbWVTY29yZSkpCn0KYGBgCgojIyBOZml4IG5ldXJvbnMgUHNldWRvdGltZSBvcmRlcmluZwoKYGBge3J9Ck5maXgubGluZWFnZS5jZWxscyA8LSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSAlPiUKICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihMaW5lYWdlID09ICJOZml4LmxpbmVhZ2UiKSAlPiUKICAgICAgICAgICAgICAgICAgICAgIHB1bGwoQmFyY29kZXMpCgojIyBGaXQgcHJpbmNpcGFsZSBjdXJ2ZSBvbiB0aGUgZGF0YSBpbiB0aGUgc3ByaW5nIHNwYWNlCmRhdGEuTmZpeCA8LSBhcy5kYXRhLmZyYW1lKEFsbGNlbGxzLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1tOZml4LmxpbmVhZ2UuY2VsbHMsMToyXSkKCmZpdCA8LSBwcmluY2lwYWxfY3VydmUoYXMubWF0cml4KGRhdGEuTmZpeFssMToyXSksCiAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoZXI9J3Ntb290aF9zcGxpbmUnLAogICAgICAgICAgICAgICAgICAgICAgIHRyYWNlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyZXRjaD0yKQoKTmZpeC5wYy5saW5lIDwtIGFzLmRhdGEuZnJhbWUoZml0JHNbb3JkZXIoZml0JGxhbWJkYSksXSkgI1RoZSBwcmluY2lwYWwgY3VydmUgc21vb3RoZWQKZGF0YS5OZml4JFBzZXVkb3RpbWVTY29yZSA8LSBmaXQkbGFtYmRhL21heChmaXQkbGFtYmRhKQoKZGF0YS5OZml4JENsdXN0ZXIgPC0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEgJT4lCiAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihMaW5lYWdlID09ICJOZml4LmxpbmVhZ2UiKSAlPiUKICAgICAgICAgICAgICAgICAgICAgcHVsbChOZXdDbHVzdGVySUQpCgoKIyBEaXJlY3Rpb24gb2YgdGhlIG1hdHVyYXRpb24gc2NvcmUgdXNpbmcgTmVzIGV4cHJlc3Npb24gKHJldmVydGUgaWYgcG9zaXRpdmUgY29ycmVsYXRpb24pCmlmIChjb3IoZGF0YS5OZml4JFBzZXVkb3RpbWVTY29yZSwgQWxsY2VsbHMuZGF0YUBkYXRhWydIbWdhMicsIE5maXgubGluZWFnZS5jZWxsc10pID4gMCkgewogIGRhdGEuTmZpeCRQc2V1ZG90aW1lU2NvcmUgPC0gLShkYXRhLk5maXgkUHNldWRvdGltZVNjb3JlIC0gbWF4KGRhdGEuTmZpeCRQc2V1ZG90aW1lU2NvcmUpKQp9CmBgYAoKIyMgQ29tYmluZSBib3RoIHRyYWplY3Rvcnkgb3JkZXJpbmcKCmBgYHtyfQpQc2V1ZG90aW1lIDwtIHJiaW5kKGRhdGEuTnI0YTIgJT4lIGRwbHlyOjpzZWxlY3QoUHNldWRvdGltZVNjb3JlKSwKICAgICAgICAgICAgICAgICAgICBkYXRhLk5maXggJT4lIGRwbHlyOjpzZWxlY3QoUHNldWRvdGltZVNjb3JlKSkKCkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJFBzZXVkb3RpbWUgPC0gUHNldWRvdGltZVtyb3duYW1lcyhBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSksXQpgYGAKCgpgYGB7ciBmaWcuZGltPWMoOCwgNil9CiNQbG90IFBzZXVkb3RpbWUgc2NvcmUgd2l0aCB0aGUgMiBwcmluY2lwYWwgY3VydmVzCmRhdGEgPC0gYXMuZGF0YS5mcmFtZShBbGxjZWxscy5kYXRhQGRyJHNwcmluZ0BjZWxsLmVtYmVkZGluZ3NbLDE6Ml0pCmRhdGEkUHNldWRvdGltZVNjb3JlIDwtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJFBzZXVkb3RpbWUKCmNvbHMgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKG4gPTExLCBuYW1lID0gIlNwZWN0cmFsIikpKDEwMCkKCmdncGxvdChkYXRhLCBhZXMoc3ByaW5nMSwgc3ByaW5nMikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1Qc2V1ZG90aW1lU2NvcmUpLCBzaXplPTIsIHNoYXBlPTE2KSArIAogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzPXJldihjb2xzKSwgbmFtZT0nU3BldWRvdGltZSBzY29yZScpICsKICBnZW9tX2xpbmUoZGF0YT1OZml4LnBjLmxpbmUsIGNvbG9yPSIjY2MzOTFiIiwgc2l6ZT0wLjc3KSArCiAgZ2VvbV9saW5lKGRhdGE9TnI0YTIucGMubGluZSwgY29sb3I9IiMwMjZjOWEiLCBzaXplPTAuNzcpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiQWxsY2VsbHMuZGF0YSIpXSkKYGBgCgoKIyBGaW5kIERFRyBiZXR3ZWVuIHRoZSB0d28gdHJhamVjdG9yaWVzIGFuZCBhbG9uZyB0aGUgcHNldWRvdGltZSAKCiMjIEZpbHRlciBnZW5lIGNvdW50cyBtYXRyaXgKYGBge3J9CiNGaWx0ZXIgZ2VuZXMKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhBbGxjZWxscy5kYXRhQHJhdy5kYXRhID4gMCkKZ2VuZXMudXNlIDwtIG5hbWVzKHggPSBudW0uY2VsbHNbbnVtLmNlbGxzID49IDEwXSkKQWxsY2VsbHMuZGF0YUByYXcuZGF0YSA8LSBBbGxjZWxscy5kYXRhQHJhdy5kYXRhW2dlbmVzLnVzZSwgXQoKIyBOb3JtYWxpemF0aW9uIGFuZCB2YXJpYWJsZSBnZW5lIHNlbGVjdGlvbgpBbGxjZWxscy5kYXRhIDwtIE5vcm1hbGl6ZURhdGEob2JqZWN0ID0gQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUuZmFjdG9yID0gcm91bmQobWVkaWFuKEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJG5VTUkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQoKQWxsY2VsbHMuZGF0YSA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBBbGxjZWxscy5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BlcnNpb24uZnVuY3Rpb24gPSBMb2dWTVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeC5sb3cuY3V0b2ZmID0gMC4wMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4LmhpZ2guY3V0b2ZmID0gNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5LmN1dG9mZiA9IDEuMywgZG8ucGxvdCA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheS5wcm9ncmVzcyA9IEYpCmxlbmd0aChBbGxjZWxscy5kYXRhQHZhci5nZW5lcykKYGBgCgojIyBJbml0aWFsaXplIGEgbW9ub2NsZSBvYmplY3QKCmBgYHtyfQojIFRyYW5zZmVydCBtZXRhZGF0YQptZXRhLmRhdGEgPC0gZGF0YS5mcmFtZShiYXJjb2RlID0gcm93bmFtZXMoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICBDbHVzdGVyID0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkQ2x1c3Rlci5pZGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgTGluZWFnZSA9IEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJExpbmVhZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgIFBzZXVkb3RpbWUuU2NvcmUgPSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRQc2V1ZG90aW1lLAogICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSByb3duYW1lcyhBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSkpCgpBbm5vdC5kYXRhICA8LSBuZXcoJ0Fubm90YXRlZERhdGFGcmFtZScsIGRhdGEgPSBtZXRhLmRhdGEpCgojIFRyYW5zZmVydCBjb3VudCBkYXRhCmNvdW50LmRhdGEgPSBkYXRhLmZyYW1lKGdlbmVfc2hvcnRfbmFtZSA9IHJvd25hbWVzKEFsbGNlbGxzLmRhdGFAcmF3LmRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSByb3duYW1lcyhBbGxjZWxscy5kYXRhQHJhdy5kYXRhKSkKCmZlYXR1cmUuZGF0YSA8LSBuZXcoJ0Fubm90YXRlZERhdGFGcmFtZScsIGRhdGEgPSBjb3VudC5kYXRhKQoKIyBDcmVhdGUgdGhlIENlbGxEYXRhU2V0IG9iamVjdApnYm1fY2RzIDwtIG5ld0NlbGxEYXRhU2V0KGFzLm1hdHJpeChBbGxjZWxscy5kYXRhQHJhdy5kYXRhKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwaGVub0RhdGEgPSBBbm5vdC5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVEYXRhID0gZmVhdHVyZS5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxvd2VyRGV0ZWN0aW9uTGltaXQgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25GYW1pbHkgPSBuZWdiaW5vbWlhbCgpKQpgYGAKCmBgYHtyfQpnYm1fY2RzIDwtIGVzdGltYXRlU2l6ZUZhY3RvcnMoZ2JtX2NkcykKZ2JtX2NkcyA8LSBlc3RpbWF0ZURpc3BlcnNpb25zKGdibV9jZHMpCmdibV9jZHMgPC0gZGV0ZWN0R2VuZXMoZ2JtX2NkcywgbWluX2V4cHIgPSAwLjEpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiQWxsY2VsbHMuZGF0YSIsICJnYm1fY2RzIildKQpgYGAKCiMjIFRlc3QgZWFjaCBnZW5lIHRyZW5kIG92ZXIgcHNldWRvdGltZSBzY29yZQoKYGBge3J9CiMgRXhjbHVkZSBjZWxsIGN5Y2xlIGFzc29jaWF0ZWQgZ2VuZXMKQ0NnZW5lcyA8LSBhcy5jaGFyYWN0ZXIocmVhZC50YWJsZSgiLi9Qcm9nZW5pdG9ycy9DZWxsQ3ljbGVHZW5lcy5jc3YiLCBzZXAgPSAiXHQiLCBoZWFkZXIgPSBGKVssMV0pCklucHV0LmdlbmVzIDwtIEFsbGNlbGxzLmRhdGFAdmFyLmdlbmVzWyFBbGxjZWxscy5kYXRhQHZhci5nZW5lcyAlaW4lIENDZ2VuZXNdCmBgYAoKYGBge3J9ClNwZXVkb3RpbWUubGluZWFnZXMuZGlmZiA8LSBkaWZmZXJlbnRpYWxHZW5lVGVzdChnYm1fY2RzW0lucHV0LmdlbmVzLF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbE1vZGVsRm9ybXVsYVN0ciA9ICJ+c20ubnMoUHNldWRvdGltZS5TY29yZSwgZGYgPSAzKSpMaW5lYWdlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y2VkTW9kZWxGb3JtdWxhU3RyID0gIn5zbS5ucyhQc2V1ZG90aW1lLlNjb3JlLCBkZiA9IDMpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IGRldGVjdENvcmVzKCkgLSAyKQoKI0ZpbHRlciBiYXNlZCBvbiBGRFIKU3BldWRvdGltZS5saW5lYWdlcy5kaWZmLmZpbHRlcmVkIDwtIFNwZXVkb3RpbWUubGluZWFnZXMuZGlmZiAlPiUgZmlsdGVyKHF2YWwgPCA1ZS0yKQpgYGAKCiMjIEZpbmQgZGlyZWN0aW9uIG9mIHRoZSBERUcKCldlIGZpbmQgZGlyZWN0aW9uIG9mIHRoZSBERUcgYnkgY2FsY3VsYXRpbmcgdGhlIGFyZWEgYmV0d2VlbiBjdXJ2ZXMgKEFCQykgZm9yIGJyYW5jaC1kZXBlbmRlbnQgZ2VuZXMgYnkgYWRhcHRpbmcgdGhlIG1vbm9jbGUgcGFja2FnZSBmdW5jdGlvbiBgY2FsQUJDc2AuIEdlbmVzIHNwZWNpZmljIEFCQyBpcyBjb21wdXRlZCBvbiBzbW9vdGhlZCBleHByZXNzaW9uIHZhbHVlIG92ZXIgMTAwIHBvaW50cyBhbG9uZyB0aGUgcHNldWRvdGltZQkKCiMjIyBTbW9vdGggZ2VuZSBleHByZXNzaW9uIGFsb25nIHBzZXVkb3RpbWUgCmBgYHtyfQojIENyZWF0ZSBhIG5ldyBwc2V1ZG8tRFYgdmVjdG9yIG9mIDUwMCBwb2ludHMKblBvaW50cyA8LSAxMDAKCm5ld19kYXRhID0gbGlzdCgpCmZvciAoTGluZWFnZSBpbiB1bmlxdWUocERhdGEoZ2JtX2NkcykkTGluZWFnZSkpewogIG5ld19kYXRhW1tsZW5ndGgobmV3X2RhdGEpICsgMV1dID0gZGF0YS5mcmFtZShQc2V1ZG90aW1lLlNjb3JlID0gc2VxKG1pbihwRGF0YShnYm1fY2RzKSRQc2V1ZG90aW1lLlNjb3JlKSwgbWF4KHBEYXRhKGdibV9jZHMpJFBzZXVkb3RpbWUuU2NvcmUpLCBsZW5ndGgub3V0ID0gblBvaW50cyksIExpbmVhZ2U9TGluZWFnZSkKfQoKbmV3X2RhdGEgPSBkby5jYWxsKHJiaW5kLCBuZXdfZGF0YSkKCiMgU21vb3RoIGdlbmUgZXhwcmVzc2lvbgpjdXJ2ZV9tYXRyaXggPC0gZ2VuU21vb3RoQ3VydmVzKGdibV9jZHNbYXMuY2hhcmFjdGVyKFNwZXVkb3RpbWUubGluZWFnZXMuZGlmZi5maWx0ZXJlZCRnZW5lX3Nob3J0X25hbWUpLF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJlbmRfZm9ybXVsYSA9ICJ+c20ubnMoUHNldWRvdGltZS5TY29yZSwgZGYgPSAzKSpMaW5lYWdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxhdGl2ZV9leHByID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdfZGF0YSA9IG5ld19kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzPSBkZXRlY3RDb3JlcygpIC0gMikKYGBgCgojIyMgQ29tcHV0ZSB0aGUgQUJDIGZvciBlYWNoIGdlbmVzCmBgYHtyfQojIEV4dHJhY3QgbWF0cml4IGNvbnRhaW5pbmcgU21vb3RoIGN1cnZlcyBmb3IgZWFjaCBsaW5lYWdlcwpOcjRhMl9jdXJ2ZV9tYXRyaXggPC0gY3VydmVfbWF0cml4WywgMTpuUG9pbnRzXSAjIHRoZSBmaXJzdCAxMDAgcG9pbnRzIGNvcnJlc3BvbmQgdG8gTnI0YTIgY2VsbHMKTmZpeF9jdXJ2ZV9tYXRyaXggPC0gY3VydmVfbWF0cml4WywgKG5Qb2ludHMgKyAxKTooMiAqIG5Qb2ludHMpXQogIApBQkNzX3JlcyA8LSBOcjRhMl9jdXJ2ZV9tYXRyaXggLSBOZml4X2N1cnZlX21hdHJpeCAjIERpcmVjdGlvbiBvZiB0aGUgY29tcGFyaXNvbiA6IHBvc3RpdmUgQUJDcyA8PT4gVXByZWd1bGF0ZWQgaW4gTnI0YTIgbGluZWFnZQpJTFJfcmVzIDwtIGxvZzIoTnI0YTJfY3VydmVfbWF0cml4LyAoTmZpeF9jdXJ2ZV9tYXRyaXggKyAwLjEpKSAjIEF2ZXJhZ2UgbG9nRkMgYmV0d2VlbiB0aGUgMiBjdXJ2ZXMKICAKQUJDc19yZXMgPC0gYXBwbHkoQUJDc19yZXMsIDEsIGZ1bmN0aW9uKHgsIG5Qb2ludHMpIHsKICAgICAgICAgICAgICAgICAgYXZnX2RlbHRhX3ggPC0gKHhbMTooblBvaW50cyAtIDEpXSArIHhbMjooblBvaW50cyldKS8yCiAgICAgICAgICAgICAgICAgIHN0ZXAgPC0gKDEwMC8oblBvaW50cyAtIDEpKQogICAgICAgICAgICAgICAgICByZXMgPC0gcm91bmQoc3VtKGF2Z19kZWx0YV94ICogc3RlcCksIDMpCiAgICAgICAgICAgICAgICAgIHJldHVybihyZXMpfSwKICAgICAgICAgICAgICAgICAgblBvaW50cyA9IG5Qb2ludHMpICMgQ29tcHV0ZSB0aGUgYXJlYSBiZWxvdyB0aGUgY3VydmUKICAKQUJDc19yZXMgPC0gY2JpbmQoQUJDc19yZXMsIElMUl9yZXNbLG5jb2woSUxSX3JlcyldKQpjb2xuYW1lcyhBQkNzX3Jlcyk8LSBjKCJBQkNzIiwgIkVuZHBvaW50X0lMUiIpCgojIEltcG9ydCBBQkMgdmFsdWVzIGludG8gdGhlIERFIHRlc3QgcmVzdWx0cyB0YWJsZQpTcGV1ZG90aW1lLmxpbmVhZ2VzLmRpZmYuZmlsdGVyZWQgPC0gY2JpbmQoU3BldWRvdGltZS5saW5lYWdlcy5kaWZmLmZpbHRlcmVkWywxOjRdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQUJDc19yZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTcGV1ZG90aW1lLmxpbmVhZ2VzLmRpZmYuZmlsdGVyZWRbLDU6Nl0pCmBgYAoKIyBDbHVzdGVyIGdlbmVzIGJ5IGV4cHJlc3Npb24gcHJvZmlsZXMgYWxvbmcgdGhlIHR3byB0cmFqZWN0b3JpZXMKCiMjIE5yNGEyIG5ldXJvbnMgc3BlY2lmaWMgdHJhbnNjcmlwdGlvbmFsIHRyYWplY3RvcmllcwoKYGBge3J9CiMgRXh0cmFjdCBOcjRhMiBuZXVyb25zIHRyYWplY3RvcnkgZ2VuZXMKTnI0YTIucmVzIDwtIGFzLmRhdGEuZnJhbWUoU3BldWRvdGltZS5saW5lYWdlcy5kaWZmLmZpbHRlcmVkW1NwZXVkb3RpbWUubGluZWFnZXMuZGlmZi5maWx0ZXJlZCRBQkNzID4gMCxdKQpOcjRhMi5nZW5lcyA8LSByb3cubmFtZXMoTnI0YTIucmVzKQpOcjRhMl9jdXJ2ZV9tYXRyaXggPC0gTnI0YTJfY3VydmVfbWF0cml4W3Jvd25hbWVzKE5yNGEyX2N1cnZlX21hdHJpeCkgJWluJSBOcjRhMi5nZW5lcywgXQpgYGAKCmBgYHtyfQojIEdyb3VwZSBnZW5lcyBpbiA2IGNsdXN0ZXJzIGJ5IHBhcnRpdGlvbmluZyByb3VuZCBtZWRvaWRzCk5yNGEyLmdlbmVzLmNsdXN0ZXJzIDwtIGNsdXN0ZXI6OnBhbShhcy5kaXN0KCgxIC0gY29yKE1hdHJpeDo6dChOcjRhMl9jdXJ2ZV9tYXRyaXgpLCBtZXRob2QgPSAic3BlYXJtYW4iKSkpLCBrPTYpCgojIENyZWF0ZSBhIGRhdGFmcmFtZSBzdG9yaW5nIERFRyB0ZXN0IGFuZCBjbHVzdGVyaW5nIHJlc3VsdHMKTnI0YTIuR2VuZS5keW5hbWlxdWUgPC0gZGF0YS5mcmFtZShHZW5lPSBuYW1lcyhOcjRhMi5nZW5lcy5jbHVzdGVycyRjbHVzdGVyaW5nKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsPU5yNGEyLnJlcyRwdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF2YWw9TnI0YTIucmVzJHF2YWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQUJDcz1OcjRhMi5yZXMkQUJDcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5lLkNsdXN0ZXJzPSBwYXN0ZTAoIkNsdXN0LiIsIE5yNGEyLmdlbmVzLmNsdXN0ZXJzJGNsdXN0ZXJpbmcpKSAlPiUgYXJyYW5nZShHZW5lLkNsdXN0ZXJzKQoKcm93Lm5hbWVzKE5yNGEyLkdlbmUuZHluYW1pcXVlKSA8LSBOcjRhMi5HZW5lLmR5bmFtaXF1ZSRHZW5lCgp3cml0ZS50YWJsZShOcjRhMi5HZW5lLmR5bmFtaXF1ZSwgIi4vTnI0YTIuR2VuZS5keW5hbWlxdWUuY3N2Iiwgc2VwPSI7IikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOSwgNSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gN0QifQpTb3J0ZWQuZ2VuZS5keW4gPC0gTnI0YTIuR2VuZS5keW5hbWlxdWUgJT4lIGFycmFuZ2UoZmFjdG9yKEdlbmUuQ2x1c3RlcnMsIGxldmVscyA9IHBhc3RlMCgiQ2x1c3QuIixjKDMsNiwxLDIsNSw0KSkpKQpyb3duYW1lcyhTb3J0ZWQuZ2VuZS5keW4pIDwtIFNvcnRlZC5nZW5lLmR5biRHZW5lCgphbm5vLmNvbG9ycyA8LSBsaXN0KGxpbmVhZ2UgPSBjKE5maXg9IiNjYzM5MWIiLCBOcjRhMj0iIzAyNmM5YSIpKQoKcGhlYXRtYXA6OnBoZWF0bWFwKGN1cnZlX21hdHJpeFthcy5jaGFyYWN0ZXIoU29ydGVkLmdlbmUuZHluJEdlbmUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoMjAwOjEwMSwgI05maXggcG9pbnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMToxMDApXSwgI05yNGEyIHBvaW50cwogICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwKICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IEYsCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHMgPSBGLAogICAgICAgICAgICAgICAgICAgZ2Fwc19yb3cgPSBjdW1zdW0oYXMubnVtZXJpYyh0YWJsZShTb3J0ZWQuZ2VuZS5keW4kR2VuZS5DbHVzdGVycylbcGFzdGUwKCJDbHVzdC4iLGMoMyw2LDEsMiw1LDQpKV0pKSwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fcm93ID0gU29ydGVkLmdlbmUuZHluICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2wgPSBkYXRhLmZyYW1lKGxpbmVhZ2UgPSByZXAoYygiTnI0YTIiLCAiTmZpeCIpLCBlYWNoPTEwMCkpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5vLmNvbG9ycywKICAgICAgICAgICAgICAgICAgIHNob3dfY29sbmFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IFQsCiAgICAgICAgICAgICAgICAgICBmb250c2l6ZV9yb3cgPSAyLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSByZXYoYnJld2VyLnBhbCgxMSwiUmRCdSIpKSwKICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgtNCw0LCBsZW5ndGgub3V0ID0gMTEpLAogICAgICAgICAgICAgICAgICAgbWFpbiA9ICJOcjRhMiBjZWxscyBlbnJpY2hlZCBnZW5lcyBleHByZXNzaW9uIGFsb25nIHBzZXVkb3RpbWUiKQpgYGAKCgojIyBOZml4IG5ldXJvbnMgc3BlY2lmaWMgdHJhbnNjcmlwdGlvbmFsIHRyYWplY3RvcmllcwoKYGBge3J9CiMgRXh0cmFjdCBOZml4IG5ldXJvbnMgdHJhamVjdG9yeSBnZW5lcwpOZml4LnJlcyA8LSBhcy5kYXRhLmZyYW1lKFNwZXVkb3RpbWUubGluZWFnZXMuZGlmZi5maWx0ZXJlZFtTcGV1ZG90aW1lLmxpbmVhZ2VzLmRpZmYuZmlsdGVyZWQkQUJDcyA8IDAsXSkKTmZpeC5nZW5lcyA8LSByb3cubmFtZXMoTmZpeC5yZXMpCk5maXhfY3VydmVfbWF0cml4IDwtIE5maXhfY3VydmVfbWF0cml4W3Jvd25hbWVzKE5maXhfY3VydmVfbWF0cml4KSAlaW4lIE5maXguZ2VuZXMsIF0KYGBgCgpgYGB7cn0KIyBHcm91cGUgZ2VuZXMgaW4gNiBjbHVzdGVycyBieSBwYXJ0aXRpb25pbmcgcm91bmQgbWVkb2lkcwpOZml4LmdlbmVzLmNsdXN0ZXJzIDwtIGNsdXN0ZXI6OnBhbShhcy5kaXN0KCgxIC0gY29yKE1hdHJpeDo6dChOZml4X2N1cnZlX21hdHJpeCksIG1ldGhvZCA9ICJzcGVhcm1hbiIpKSksIGs9NikKCiMgQ3JlYXRlIGEgZGF0YWZyYW1lIHN0b3JpbmcgREVHIHRlc3QgYW5kIGNsdXN0ZXJpbmcgcmVzdWx0cwpOZml4LkdlbmUuZHluYW1pcXVlIDwtIGRhdGEuZnJhbWUoR2VuZT0gbmFtZXMoTmZpeC5nZW5lcy5jbHVzdGVycyRjbHVzdGVyaW5nKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsPU5maXgucmVzJHB2YWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbD1OZml4LnJlcyRxdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFCQ3M9TmZpeC5yZXMkQUJDcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5lLkNsdXN0ZXJzPSBwYXN0ZTAoIkNsdXN0LiIsIE5maXguZ2VuZXMuY2x1c3RlcnMkY2x1c3RlcmluZykpICU+JSBhcnJhbmdlKEdlbmUuQ2x1c3RlcnMpCgpyb3cubmFtZXMoTmZpeC5HZW5lLmR5bmFtaXF1ZSkgPC0gTmZpeC5HZW5lLmR5bmFtaXF1ZSRHZW5lCgp3cml0ZS50YWJsZShOZml4LkdlbmUuZHluYW1pcXVlLCAiLi9OZml4LkdlbmUuZHluYW1pcXVlLmNzdiIsIHNlcD0iOyIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDksIDUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDdDIn0KU29ydGVkLmdlbmUuZHluIDwtIE5maXguR2VuZS5keW5hbWlxdWUgJT4lIGFycmFuZ2UoZmFjdG9yKEdlbmUuQ2x1c3RlcnMsIGxldmVscyA9IHBhc3RlMCgiQ2x1c3QuIixjKDYsNCwxLDIsMyw1KSkpKQpyb3duYW1lcyhTb3J0ZWQuZ2VuZS5keW4pIDwtIFNvcnRlZC5nZW5lLmR5biRHZW5lCgoKcGhlYXRtYXA6OnBoZWF0bWFwKGN1cnZlX21hdHJpeFthcy5jaGFyYWN0ZXIoU29ydGVkLmdlbmUuZHluJEdlbmUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoMjAwOjEwMSwgI05maXggcG9pbnRzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMToxMDApXSwgI05yNGEyIHBvaW50cwogICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwKICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IEYsCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHMgPSBGLAogICAgICAgICAgICAgICAgICAgZ2Fwc19yb3cgPSBjdW1zdW0oYXMubnVtZXJpYyh0YWJsZShTb3J0ZWQuZ2VuZS5keW4kR2VuZS5DbHVzdGVycylbcGFzdGUwKCJDbHVzdC4iLGMoNiw0LDEsMiwzLDUpKV0pKSwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fcm93ID0gU29ydGVkLmdlbmUuZHluICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2wgPSBkYXRhLmZyYW1lKGxpbmVhZ2UgPSByZXAoYygiTnI0YTIiLCAiTmZpeCIpLCBlYWNoPTEwMCkpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5vLmNvbG9ycywKICAgICAgICAgICAgICAgICAgIHNob3dfY29sbmFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IFQsCiAgICAgICAgICAgICAgICAgICBmb250c2l6ZV9yb3cgPSAyLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSByZXYoYnJld2VyLnBhbCgxMSwiUmRCdSIpKSwKICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgtNCw0LCBsZW5ndGgub3V0ID0gMTEpLAogICAgICAgICAgICAgICAgICAgbWFpbiA9ICJOZml4IGNlbGxzIGVucmljaGVkIGdlbmVzIGV4cHJlc3Npb24gYWxvbmcgcHNldWRvdGltZSIpCmBgYAojIFBsb3QgcmVsZXZhbnQgZ2VuZXMgdHJlbmQKCmBgYHtyfQojIGxvYWQgY3VzdG9tIHBsb3R0aW5nIGZ1bmN0aW9ucwpzb3VyY2UoIi4vZnVuY3Rpb25zL1RyYWplY3Rvcmllc1Bsb3RGdW5jdGlvbnMuUiIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDEwLDUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDdFIn0KUGxvdC5HZW5lcy50cmVuZChBbGxjZWxscy5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiTmZpYiIsICJEYngxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXJvZDYiLCAiUGJ4MyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJQY3A0IiwgIkJhcmhsMiIpLAogICAgICAgICAgICAgICAgIGNvbG9yLmJ5ID0gImxpbmVhZ2UiLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOSw1KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA3RSJ9ClBsb3QuR2VuZXMudHJlbmQoQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIk5ldXJvZDQiLCAiTmV1cm9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJaZmh4MyIsICJUdWJiMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJIZXkxIiwgIk1hcHQiKSwKICAgICAgICAgICAgICAgICBjb2xvci5ieSA9ICJsaW5lYWdlIiwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDksNSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gUzdCIn0KUGxvdC5HZW5lcy50cmVuZChBbGxjZWxscy5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiVGJyMSIsICJFbXgxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXJvZDEiLCAiSGV5MSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZXVyb2QyIiwgIkZscnQzIiksCiAgICAgICAgICAgICAgICAgY29sb3IuYnkgPSAibGluZWFnZSIsCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg5LDUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIFM3QiJ9ClBsb3QuR2VuZXMudHJlbmQoQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIk5maWEiLCAiRG1ydDMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiQ25yMSIsICJTbGMzMGExMCIpLAogICAgICAgICAgICAgICAgIGNvbG9yLmJ5ID0gImxpbmVhZ2UiLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOSw1KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiBTN0IifQpQbG90LkdlbmVzLnRyZW5kKEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJFcGhhMyIsICJQZGxpbTQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiVG94IiwgIlRmYXAyYyIpLAogICAgICAgICAgICAgICAgIGNvbG9yLmJ5ID0gImxpbmVhZ2UiLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCmBgYHtyIGZpZy5kaW09Yyg5LDUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIFM3QiJ9ClBsb3QuR2VuZXMudHJlbmQoQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIkVwaGEzIiwgIlBkbGltNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJUb3giLCAiVGZhcDJjIiksCiAgICAgICAgICAgICAgICAgY29sb3IuYnkgPSAibGluZWFnZSIsCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg5LDUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIFM3QiJ9ClBsb3QuR2VuZXMudHJlbmQoQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIk5ldXJvZzEiLCAiRW9tZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiQnRnMiIsICJGb3hnMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJFbXgyIiksCiAgICAgICAgICAgICAgICAgY29sb3IuYnkgPSAibGluZWFnZSIsCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCiMgU2Vzc2lvbiBJbmZvCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUgsJU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGA=